package org.openzip.openzip.archiving.logic;

import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.openzip.openzip.gui.util.FileUtil;


/** This class serves as a data model holding files which have been selected.
 *  It provides flexible way of keeping all selected files from different gui
 *  sources at one place.
 *  
 *  @author Synthetic
 */
public class SelectedFilesModel implements IObservable {

	private Collection<File> selectedFiles;
	private Set<IObserver> observers;
	
	public SelectedFilesModel() {
		//I chose Set, because we (AFAIK) don't need a single File to be listed
		//twice.
		selectedFiles = new HashSet<File>();
		observers = new HashSet<IObserver>();
	}
	
	/** Adds a single file to selection model */
	public void addFile(File file) {
		Collection<File> children = FileUtil.getLeafs(file, false);
		children.removeAll(selectedFiles);
		selectedFiles.addAll(children);
		notifyObservers(children, true);
		System.out.println("File has been added: " + file.getName());
	}
	
	/** Removes single file received as parameter from selection model */
	public void removeFile(File file) {
		Collection<File> children = FileUtil.getLeafs(file, false);
		children.retainAll(selectedFiles);
		selectedFiles.removeAll(children);
		notifyObservers(children, false);
		System.out.println("File has been removed: " + file.getName());
	}
	
	public boolean isFileSelected(File file) {
		if (selectedFiles.contains(file)) {
			return true;
		}
		return false;
	}
	
	public int getFilesCount() {
		return selectedFiles.size();
	}
	
//========== Methods bellow this line are not used at the moment ;-) ===========	
	/** This method returns children files of parent given as parameter.
	 *  Children may be both files and directories. Child is a direct subfile or
	 *  subdirectory of parent.
	 *  
	 *  @param parent Parent File - only directory makes sense(file cannot have
	 * 			children)
	 *  @return
	 */
	public Collection<File> getSelectedChildrenFiles(File parent) {
		Collection<File> selectedChildrenFiles = new HashSet<File>();
		
		File[] allChildrenFiles = parent.listFiles();
		if (allChildrenFiles == null) {
			//File.listFiles() returns empty array for empty directory

			//File.listFiles() returns null for File being file or I/O error
			throw new IllegalArgumentException("Argument is not a directory");
		}
		for (File child : allChildrenFiles) {
			if (selectedFiles.contains(child)) {
				selectedChildrenFiles.add(child);
			}
		}
		return selectedChildrenFiles;
	}
	
	public void isAnyFileSelected(File parentDirectory) {
		
	}
	
	/** Files received as parameter is set as the model data. Which causes the
	 *  original data from the model to be lost.
	 *  
	 *  @param selectedFiles Files which will be set as new data for the model
	 */
	public void setSelectedFiles(Collection<File> selectedFiles) {
		this.selectedFiles = selectedFiles;
	}
	
	/** Gives all selected files
	 * 
	 * @return All selected files as a <code>Collection<File></code>
	 */
	public Collection<File> getSelectedFiles() {
		return selectedFiles;
	}

//=============== IObservable interface implementation methods =================
	public void notifyObservers(Collection<File> modified, boolean added) {
		for (IObserver o : observers) {
			o.update(this, modified, added);
		}
	}
	
	public void registerObserver(IObserver o) {
		observers.add(o);
	}
	
	public void unregisterObserver(IObserver o) {
		observers.remove(o);
	}
	
}
